<?php

/**
 * Список результатов запроса
 */
class DM_Db_List implements Iterator, ArrayAccess, Countable {

    protected $adapter = null;
    protected $model = null;
    protected $data = [];

    /**
     * Конструктор
     * @param array $data           Данные
     * @param DM_Db_Model $model    Родительская модель
     */
    public function __construct($data = null, &$model = null, &$adapter = null) {
        if (is_array($data)) {
            $this->data = $data;
        }

        // set model
        if (!empty($model) && $model instanceof DM_Db_Model) {
            $this->model = $model;
        }

        // set adapter
        if (!empty($adapter) && $adapter instanceof DM_Db_Adapter) {
            $this->adapter = $adapter;
        } else {
            $this->adapter = &DM_Db_Adapter::$defaultAdapter;
        }
    }

    function rewind() {
        return reset($this->data);
    }

    function current() {
        return current($this->data);
    }

    function key() {
        return key($this->data);
    }

    function next() {
        return next($this->data);
    }

    function valid() {
        return key($this->data) !== null;
    }

    public function offsetSet($offset, $value) {
        if (is_null($offset)) {
            $this->data[] = $value;
        } else {
            $this->data[$offset] = $value;
        }
    }

    public function offsetExists($offset) {
        return isset($this->data[$offset]);
    }

    public function offsetUnset($offset) {
        unset($this->data[$offset]);
    }

    public function offsetGet($offset) {
        return isset($this->data[$offset]) ? $this->data[$offset] : null;
    }

    function & getIterator() {
        return new ArrayIterator($this->data);
    }

    public function count() {
        return count($this->data);
    }

    public function first() {
        if (!empty($this->data)) {
            return reset($this->data);
        }
        return FALSE;
    }

    public function last() {
        if (!empty($this->data)) {
            return end($this->data);
        }
        return FALSE;
    }

    /**
     * Групповое сохранение записей в таблицу - механизм ActiveRecord
     */
    public function save() {
        if (!empty($this->data)) {
            $this->adapter->beginTransaction();
            foreach ($this->data as &$row) {
                $row->save();
            }
            $this->adapter->endTransaction();
        }
    }

    /**
     * Групповое удаление строк из базы данных - механизм ActiveRecord
     */
    public function remove() {
        if (!empty($this->data)) {
            $this->adapter->beginTransaction();
            foreach ($this->data as &$row) {
                $row->remove();
            }
            $this->adapter->endTransaction();
        }
    }

    /**
     * Convert list into array
     * @return array
     */
    public function toArray() {
        $result = [];
        if (!empty($this->data)) {
            foreach ($this->data as $row) {
                $result[] = $row->toArray();
            }
        }
        return $result;
    }

    /**
     * Получение ассоциативного массива, где ключем строки DM_Db_Row будет заданное поле $key
     * Если параметр $mutiColumnValue == true, тогда при совпадении ключевого поля значение по ключу будет формироваться как массив строк DM_Db_Row
     * @param type $keyField        Key field name
     * @param type $mutiColumnValue Pack value as array
     * @param type $keyPrintFormat  sprintf key format
     */
    public function getAssoc($keyField, $mutiColumnValue = false, $keyPrintFormat = '%s') {
        if (count($this->data)) {
            if (!$mutiColumnValue) {
                foreach ($this->data as $row) {
                    $map[$row[$keyField]] = $row;
                }
            } else {
                foreach ($this->data as $row) {
                    if (!isset($map[$row[$keyField]])) {
                        $map[$row[$keyField]] = [];
                    }
                    $map[$row[$keyField]][] = $row;
                }
            }
        }
    }

    /**
     * Get results list as map, example: [ item_id = item_value,... ]
     * You can modify key use $keyPrintFormat with sprintf
     * Получаем хэш таблицу ключ=значение, из списка результатов
     * @param string $key           Key field name
     * @param strnig $value         Value field name
     * @param type $keyPrintFormat  sptrinf format string, default '%s'
     * @return array|map
     */
    public function getMap($key, $value, $keyPrintFormat = '%s') {
        if (!count($this->data)) {
            return [];
        }
        $result = [];
        foreach ($this->data as $item) {
            $result[sprintf($keyPrintFormat, $item[$key])] = $item[$value];
        }
        return $result;
    }

    /**
     * Get array of values by keyfield
     * Получаем из списка результатов массив значений, где будут только значения выбранные по указанному ключу
     * @param string $key               Key field name
     * @param string $printFormat       sptrinf format string, default '%s'
     * @return array
     */
    public function getKeys($key, $printFormat = '%s') {
        if (!count($this->data)) {
            return [];
        }
        $result = [];
        foreach ($this->data as $item) {
            if (!in_array($item[$key], $result)) {
                $result[] = sprintf($printFormat, $item[$key]);
            }
        }
        return $result;
    }

}

;
?>